﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Design;
using System.Runtime.InteropServices;

namespace XKControlLib
{
    public partial class CTextBox : UserControl
    {
        public event EventHandler EndEdit;
        public event EventHandler ZoomClick;
        [Browsable(true)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        public new event EventHandler TextChanged;
        public event EventHandler ValueChanged;


        public CTextBox()
        {
            InitializeComponent();
            txt.GotFocus += txt_GotFocus;
            this.Leave += CTextBox_Leave;
            lblCaption.MouseDown += CTextBox_MouseDown;
            lblLine.MouseDown += CTextBox_MouseDown;
            txt.MouseDown += CTextBox_MouseDown;
            Pic.MouseDown += CTextBox_MouseDown;
            lblCaption.MouseEnter += CTextBox_MouseEnter;
            lblLine.MouseEnter += CTextBox_MouseEnter;
            txt.MouseEnter += CTextBox_MouseEnter;
            Pic.MouseEnter += CTextBox_MouseEnter;
            lblCaption.MouseLeave += CTextBox_MouseLeave;
            lblLine.MouseLeave += CTextBox_MouseLeave;
            txt.MouseLeave += CTextBox_MouseLeave;
            Pic.MouseLeave += CTextBox_MouseLeave;
            lblCaption.MouseMove += CTextBox_MouseMove;
            lblLine.MouseMove += CTextBox_MouseMove;
            Pic.MouseMove += CTextBox_MouseMove;
            txt.MouseMove += CTextBox_MouseMove;
            lblCaption.MouseUp += CTextBox_MouseUp;
            lblLine.MouseUp += CTextBox_MouseUp;
            Pic.MouseUp += CTextBox_MouseUp;
            txt.MouseUp += CTextBox_MouseUp;

            BorderStyle = BorderStyle.FixedSingle;
            LayoutControl();
        }
        
        #region "MouseEvent"
        private void CTextBox_MouseUp(object sender, MouseEventArgs e)
        {
            var controls = sender as System.Windows.Forms.Control;
            var e1 = new MouseEventArgs(e.Button, e.Clicks, e.X + controls.Left, e.Y + controls.Top, e.Delta);
            this.OnMouseUp(e1);
        }

        private void CTextBox_MouseMove(object sender, MouseEventArgs e)
        {
            var controls = sender as System.Windows.Forms.Control;
            var e1 = new MouseEventArgs(e.Button, e.Clicks, e.X + controls.Left, e.Y + controls.Top, e.Delta);
            this.OnMouseMove(e1);
        }

        private void CTextBox_MouseLeave(object sender, EventArgs e)
        {
            this.OnMouseLeave(e);
        }

        private void CTextBox_MouseEnter(object sender, EventArgs e)
        {
            this.OnMouseEnter(e);
        }

        private void CTextBox_MouseDown(object sender, MouseEventArgs e)
        {
            var controls = sender as System.Windows.Forms.Control;
            var e1 = new MouseEventArgs(e.Button, e.Clicks, e.X + controls.Left, e.Y + controls.Top, e.Delta);
            this.OnMouseDown(e1);
        }
        #endregion

        private void CTextBox_Leave(object sender, EventArgs e)
        {
            if (_TextBoxType == TextBoxType.txtDate && txt.Text.Trim()!="")
            {
                if (DateTime.TryParse(this.Text, out DateTime result))
                {
                    txt.Text = DateTime.Parse(this.Text).ToString("yyyy-MM-dd");
                }
                else
                {
                    MessageBox.Show("日期格式不正确");
                    this.Focus();
                    return;
                }
            }
            Pic.Visible = false;
            if (_Enabled)
            {
                EndEdit?.Invoke(this, e);
            }
        }

        private void txt_GotFocus(object sender, EventArgs e)
        {
            if (this._TextBoxType != TextBoxType.txt && this.Enabled)
            {
                Pic.Visible = true;
            }
            this.OnGotFocus(e);
        }

        public override Color BackColor
        {
            get => base.BackColor;
            set {
                base.BackColor = value;
                LayoutControl();
            }
        }

        private void LayoutControl()
        {
            lblCaption.Left = 0;
            //lblCaption.BackColor = Color.Transparent;
            txt.Left = lblCaption.Width;
            if (Pic.Visible)
            {
                txt.Width = this.Width - lblCaption.Width - Pic.Width;
                Pic.Left = this.Width - Pic.Width;
            }
            else
            {
                txt.Width = this.Width - lblCaption.Width;
            }
            Pic.Top = (this.Height - Pic.Height) / 2;
            if (this._BorderStyle == BorderStyle.FixedSingle)
            {
                txt.BorderStyle = BorderStyle.None;
                lblLine.Visible = true;
                txt.ReadOnly = !this.Enabled;
                lblLine.BackColor = this.Enabled ? Color.Black : Color.Gray;
                txt.Top = (this.Height - txt.Height) / 2;
                lblLine.Top = txt.Top + txt.Height;
                lblCaption.Top = txt.Top;
            }
            else if (_BorderStyle == BorderStyle.Fixed3D)
            {
                txt.BorderStyle = BorderStyle.Fixed3D;
                lblLine.Visible = false;
                txt.ReadOnly = !Enabled;
                txt.BackColor = this.Enabled ? Color.White : Color.FromArgb(224, 224, 224);
                txt.Top = (this.Height - txt.Height) / 2;
                lblLine.Top = txt.Top + txt.Height;
                lblCaption.Top = (this.Height - lblCaption.Height) / 2;
            }
            else if (_BorderStyle == BorderStyle.None)
            {
                txt.BorderStyle = BorderStyle.None;
                lblLine.Visible = false;
                txt.ReadOnly = !this.Enabled;
                txt.BackColor = this.Enabled ? Color.White : Color.FromArgb(224, 224, 224);
                txt.Top = (this.Height - txt.Height) / 2;
                lblLine.Top = txt.Top + txt.Height;
                lblCaption.Top = txt.Top;
            }
            lblCaption.BackColor = this.BackColor;
            Pic.BackColor = this.BackColor;
            lblLine.Left = txt.Left;
            lblLine.Width = txt.Width;
        }

        [Browsable(true)]
        [Description("标题")]
        public string Caption
        {
            get
            {
                return lblCaption.Text;
            }
            set
            {
                lblCaption.Text = value;
            }
        }

        [Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override string Text
        {
            get
            {
                return txt.Text;
            }
            set
            {
                if (this.TextBoxType == TextBoxType.txtDate)
                {
                    if (DateTime.TryParse(value, out DateTime result))
                    {
                        this.txt.Text = DateTime.Parse(value).ToString("yyyy-MM-dd");
                    }    
                }
                else
                {
                    txt.Text = value;
                }
            }
        }

        private string _myValue;
        [Browsable(true)]
        public string Value
        {
            get
            {
                return this._myValue;
            }
            set
            {
                var tmp = value;
                this._myValue = value;
                if (tmp != value)
                {
                    ValueChanged(this, new EventArgs());
                }
            }
        }

        private TextBoxType _TextBoxType;
        public TextBoxType TextBoxType {
            get
            {
                return this._TextBoxType;
            }
            set
            {
                this._TextBoxType = value;
                if (_TextBoxType == TextBoxType.txtDate)
                {
                    Pic.Image = this.PicDate.Image;
                }
                else if (_TextBoxType == TextBoxType.txtZoom)
                {
                    Pic.Image = this.picZoom.Image;
                }
            }
        }

        private bool _Enabled = true;
        [Browsable(true)]
        public new bool Enabled
        {
            get => _Enabled;
            set
            {
                this._Enabled = value;
                LayoutControl();
            }
        }




        private BorderStyle _BorderStyle;
        [Browsable(true)]
        public new BorderStyle BorderStyle
        {
            get
            {
                return this._BorderStyle;
            }
            set
            {
                this._BorderStyle = value;
                LayoutControl();
            }
        }

        [Browsable(true)]
        public HorizontalAlignment TextAlign
        {
            get
            {
                return txt.TextAlign;
            }
            set
            {
                txt.TextAlign = value;
            }
        }

        [Browsable(true)]
        public char PasswordChar
        {
            get
            {
                return txt.PasswordChar;
            }
            set
            {
                txt.PasswordChar = value;
            }
        }

        [Browsable(true)]
        public Color CaptionColor
        {
            get
            {
                return lblCaption.ForeColor;
            }
            set
            {
                lblCaption.ForeColor = value;
            }
        }

        public int SelectionStart
        {
            get
            {
                return txt.SelectionStart;
            }
            set
            {
                txt.SelectionStart = value;
            }
        }

        [Category("杂项")]
        [Description("指定在 System.Windows.Forms.ComboBox 和 System.Windows.Forms.TextBox 控件中使用的自动完成功能的模式。")]
        public AutoCompleteMode AutoCompleteMode
        {
            get
            {
                return txt.AutoCompleteMode;
            }
            set
            {
                txt.AutoCompleteMode = value;
            }
        }

        [Category("杂项")]
        [Description("指定 System.Windows.Forms.ComboBox 和 System.Windows.Forms.TextBox 自动完成功能的源。")]
        public AutoCompleteSource AutoCompleteSource
        {
            get
            {
                return txt.AutoCompleteSource;
            }
            set
            {
                txt.AutoCompleteSource = value;
            }
        }

        [Category("杂项")]
        [Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
        [Description("包含某些 Windows 窗体控件上自动完成功能所使用的字符串集合。")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        [Localizable(true)]
        public AutoCompleteStringCollection AutoCompleteCustomSource
        {
            get
            {
                return txt.AutoCompleteCustomSource;
            }
            set
            {
                txt.AutoCompleteCustomSource = value;
            }
        }


        private void CTextBox_SizeChanged(object sender, EventArgs e)
        {
            LayoutControl();
        }

        private void lblCaption_SizeChanged(object sender, EventArgs e)
        {
            LayoutControl();
        }

        private void Pic_VisibleChanged(object sender, EventArgs e)
        {
            LayoutControl();
        }

        private void txt_TextChanged(object sender, EventArgs e)
        {
            this.Text = txt.Text;
            TextChanged?.Invoke(this, e);
            this.OnTextChanged(e);
        }

        private void Pic_Click(object sender, EventArgs e)
        {
            if (_TextBoxType == TextBoxType.txtDate)
            {
                Form frm = new Form
                {
                    Name = "calendar_frm"
                };
                MonthCalendar calendar = new MonthCalendar();
                if (DateTime.TryParse(this.Text, out DateTime result))
                {
                    calendar.SetDate(result);
                }
                calendar.Size = new Size(220, 180);
                calendar.Dock = DockStyle.Fill;
                calendar.MaxSelectionCount = 1;
                calendar.DateSelected += DateSelected;
                calendar.MouseLeave += Calendar_Leave;
                frm.Controls.Add(calendar);
                frm.ClientSize = new Size(220, 180);
                frm.StartPosition = FormStartPosition.Manual;
                frm.Location = new Point(MousePosition.X, MousePosition.Y);
                frm.TopMost = true;
                frm.ShowInTaskbar = false;
                frm.FormBorderStyle = FormBorderStyle.None;
                frm.Show();
            }
           else if (_TextBoxType == TextBoxType.txtZoom)
            {

                ZoomClick?.Invoke(this, e);
            }
        }

        private void Calendar_Leave(object sender, EventArgs e)
        {
            (sender as Control).Parent.Dispose();
        }

        private void DateSelected(object sender, DateRangeEventArgs e)
        {
            txt.Text = e.Start.ToString("yyyy-MM-dd");
            (sender as Control).Parent.Dispose();

        }

        private void txt_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F2 && TextBoxType == TextBoxType.txtZoom && this.Enabled)
            {
                ZoomClick?.Invoke(this, new EventArgs());
            }
            if (e.KeyCode == Keys.Enter)
            {
                SendKeys.SendWait("{Tab}");
            }
            this.OnKeyDown(e);
        }
    }
    public partial class BaseTextBox : TextBox
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr LoadLibrary(string lpFileName);
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams prams = base.CreateParams;
                if (LoadLibrary("msftedit.dll") != IntPtr.Zero)
                {
                    prams.ExStyle |= 0x020; // transparent   
                    prams.ClassName = "RICHEDIT50W";
                }
                return prams;
            }
        }
    }
}
